<?php
/**
 */
class UsersController extends PippoaclAppController {
	
	var $components = array('Auth','autocomplete', 'Cookie', 'Email');
	var $name       = 'Users';
    
	var $activationEmail = 'Activation <some@mail.it>';
	var $activationSubject = 'Activate Your Account';
	var $forgetEmail = 'Forget Email <some@mail.it>';
	var $forgetSubject = 'Forgot Password';
	var $resetEmail = 'Reset Password <some@mail.it>';
	var $resetSubject = 'Reset Password';

	function index() {
		$query = $this->data['User'];
		
		if (empty($query)) {
			$this->User->recursive = 0;
			$this->set('users', $this->paginate());
			
		}else{
		
			$begincontain = $this->data['User']['begincontain'];
			
			foreach($query as $key => $value)
			{
				if ($key!= "begincontain"){
					if (!empty($value)) {
						if (!empty($conditions)) {
							
								$key=$key.' LIKE';
							if ($begincontain == 0) {

								$condizioni=array($key => $value.'%');
							}else{
								$condizioni=array($key => '%'.$value.'%');
							}
							$conditions=array_merge($conditions,$condizioni);
						}else{
						
							$key=$key.' LIKE';
							if ($begincontain == 0) {

								$conditions=array($key => $value.'%');
							}else{
								$conditions=array($key => '%'.$value.'%');
							}
						}
					}
				}
			}
			
			$paginationParameters = array();
			$paginationParameters['controller'] = 'users';
			$paginationParameters['action'] = $this->action;

			if (!empty($conditions)) {
				$users = $this->paginate('User', $conditions);
			}else{
				$users = $this->paginate('User');
			}
			
			$this->set(compact('users'));
		
		}
	}

	function view($id = null) {
		if (!$id) {
			$this->Session->setFlash(__('Invalid User.', true),'flash_failure');
			$this->redirect(array('action'=>'index'));
		}
		$this->set('user', $this->User->read(null, $id));
	}
	
	function edit($id = null) {
	
		if (!$id && empty($this->data)) {
			$this->Session->setFlash(__('Invalid User.', true),'flash_failure');
			$this->redirect(array('action'=>'index'));
		}
		if (!empty($this->data)) {
			if (empty($this->data['User']['new_password']))	{
				$this->__unsetPassword();
			}
			if ($this->User->save($this->data)) {
				$this->_setParentAro($this->User->id, $this->data['User']['role_id']);
				$this->Session->setFlash(__('The User has been saved.', true),'flash_success');
				// redirect back to index page
				$this->redirect(array('action' => 'index'));
			} else {
				$this->__unsetPassword();
				$this->Session->setFlash(__('The User could not be saved. Please try again.', true),'flash_failure');
			}
		}
		if (empty($this->data)) {
			$this->data = $this->User->read(null, $id);
		}
		$roles = $this->User->Role->find('list');
		$this->set(compact('roles'));
	}
	
	function delete($id = null) {
		if (!$id) {
			$this->Session->setFlash(__('Invalid id for User.', true),'flash_failure');
			$this->redirect(array('action'=>'index'));
		}
		if ($this->User->del($id)) {
			//$this->Session->setFlash(__('User deleted', true));
			$this->Session->setFlash(__('User deleted.', true),'flash_success');

			$this->redirect(array('action'=>'index'));
		}
	}
	
	function add() {
	
		if (!empty($this->data)) {
			$this->User->create();
			if ($this->User->save($this->data)) {
				$this->Session->setFlash(__('The User has been saved.', true),'flash_success');
				// redirect back to index page
				$this->redirect(array('action' => 'index'));
			} else {
				$this->__unsetPassword();
				$this->Session->setFlash(__('The User could not be saved. Please try again.', true),'flash_failure');
			}
		}
		
		$roles = $this->User->Role->find('list');
		$this->set(compact('roles'));
	}

	/**
	 * Unsets the password fields to avoid validation and avoid blank passwords being processed.
	 * Also used when validation failed to clear old passwords.
	 *
	 * @access private
	 */
	function __unsetPassword() {
		unset($this->data['User']['new_password']);
		unset($this->data['User']['confirm_password']);
		unset($this->data['User']['password']);  // No blank passwords allowed
	}

	/**
	 * Confirms user login and writes Remember Me cookie if required.
	 *
	 * Uses CakePHP's included Auth component. Sets a  Remember Me cookie with user_id while login.
	 * If no fields entered (on load) check for presence of cookie and attempt login, deleting cookie where necessary.
	 */
	function login() {
		if ($this->Auth->user()) {
			if (!empty($this->data) && $this->data['User']['remember_me']) {
				$cookie = $this->Auth->user('id');
				$this->Cookie->write('Auth.User', $cookie, true, '+1 day');
				unset($this->data['User']['remember_me']);
			}
			$this->redirect($this->Auth->redirect());
		}
		if (empty($this->data)) {
			$cookie = $this->Cookie->read('Auth.User');
			if (!is_null($cookie)) {
				if ($this->Auth->login($cookie)) {
					//  Clear auth message, just in case we use it.
					$this->Session->del('Message.auth');
					$this->redirect($this->Auth->redirect());
				} else {//  Invalid cookie
					$this->Cookie->del('Auth.User');
				}
			}
		}
	}

	function logout(){
		$this->Session->setFlash('Good-Bye','flash_success');
		$this->Cookie->del('Auth.User');
		$this->Cookie->del('Auth.UserLogged');
		$this->redirect($this->Auth->logout());
	}

	/**
	 * Adds custom Auth->allow() and set's password = new_password for hashing through Auth
	 *
	 */
	function beforeFilter()
    {
		parent::beforeFilter();
		$this->Auth->autoRedirect = false;
        //  Hash password for data storage
		if (isset($this->data['User']['new_password'])) {
			$this->data['User']['password'] = $this->data['User']['new_password'];
		}
    }

	/**
	 * Register a new user
	 *
	 * Sends an email to the user with a confirmation link to activate the account. Modifiy email element for Admin authorization
	 *
	 */
	function register() {
		if (!empty($this->data)) {
			$this->User->create();
			if ($this->User->save($this->data, true, array('username', 'fname', 'lname', 'email', 'password'))) {
				extract($this->data['User']);
				$activation = Security::hash($username.$email.$this->User->id);
				$this->User->saveField('activation_code', $activation);
				//set default role
				$this->User->saveField('role_id',1);
				$this->set('activation_code', $activation);

				if ($this->_sendMailTemplate($email, $this->activationEmail, $this->activationSubject, 'register')) {
					$this->Session->setFlash(__('Please check your email for the activation link.',true),'flash_success');
				} else {
					$this->Session->setFlash(__('Error sending email',true),'flash_failure');
				}
				$this->redirect('/');
			} else { // clear these fields or else they'll be repopulated with hashes. Passwords should be cleared anyway.
				$this->__unsetPassword();
				$this->Session->setFlash(__('The User could not be registered. Please, try again.',true),'flash_failure');
			}
		}
	}

	/**
	 * Confirm a user's account via an activation link
	 *
	 * User is confirmed with a hash of Security::hash($username.$email.$this->User->id) stored in [activation_code]
	 *
	 */
	function activate($activation) {
		$this->recursive = -1;
		$user = $this->User->find(array('activation_code' => $activation), 'id');
		
		$this->User->id = $user['User']['id'];
		$all = $this->User->read(null, $this->User->id);
		//print_r($all);
		$user['User']['activation_code'] = null;
		$user['User']['active'] = 1;
		if (!empty($user) && $this->User->save($user, false, array('activation_code', 'active'))) {
			$this->Session->setFlash(__('User activated. Please login.',true),'flash_success');
			$this->_setParentAro($this->User->id, $all['User']['role_id']);
		} else {
			$this->Session->setFlash(__('User NOT activated.',true),'flash_failure');
		}
		$this->redirect('/');
	}

	/**
	 * Used if a user forgets their password.
	 *
	 * Generates a new random password for the user and sends them an email to the associated email address. User can search by either
	 * a username or the email address
	 */
	/**
	 * Forget password recovery
	 *
	 * Sends a reset password request to the user. They must receive this and click it to reset the passwords.
	 * Passwords are not reset on a whim. Hash stored in [password_reset]
	 * User enters username OR email address (should be unique)
	 *
	 */
	function forget() {

		if (!empty($this->data)) {
			$username = $this->data['User']['username'];
			$this->recursive = -1;

			//if ($user = $this->User->find("username = '$username' OR email = '$username'", 'fields' => 'id, email')))
			if ($user = $this->User->find(array('or' => array('username' => $username, 'email' => $username)), 'id, username, password, email'))
			{
				extract($user['User']);
				$reset_code = Security::hash($username.$id.$password);
				$this->set('reset_code', $reset_code);
				$this->User->id = $id;
				if ($this->User->savefield('password_reset', $reset_code)  &&
				$this->_sendMailTemplate($email, $this->forgetEmail, $this->forgetSubject, 'forget')) {
					$this->Session->setFlash(__('A password reset request has been sent. Check you email address: '.$email, true),'flash_success');
				} else {
					$this->Session->setFlash(__('Error resetting password. Contact Administrator', true),'flash_failure');
				}
				$this->redirect('/');
			} else {
				$this->Session->setFlash(__('User does not exist.', true),'flash_failure');
			}
		}
		
	}

	/**
	 * Reset user password
	 *
	 * Generates a new random password for the user and sends them an email to the associated email address.
	 * Uses [password_reset] from the forget function.
	 */
	function reset($hash) {
		$this->recursive = -1;
		$user = $this->User->find(array('password_reset' => $hash), 'username, id, email');
		$this->User->id = $user['User']['id'];
		if (!empty($user)) {
			extract($user['User']);
			$this->User->id = $id;
			$password = $this->_randomPassword();
			$user['User']['password'] = $this->Auth->password($password);
			$user['User']['password_reset'] = '';
			$this->set(compact('username', 'password'));
			if ($this->User->save($user, false, array('password', 'password_reset')) &&
			$this->_sendMailTemplate($email, $this->resetEmail, $this->resetSubject, 'reset')) {
				$this->Session->setFlash(__('Your password has been successully reset. Check you email address: '.$email, true),'flash_success');
			} else {
				$this->Session->setFlash(__('Error resetting password. Contact Administrator', true),'flash_failure');
			}
			$this->redirect('/');
		} else {
			$this->Session->setFlash(__('Incorrect reset code', true),'flash_failure');
		}
		$this->redirect('/');
	}

	/**
	 * Produces a random password
	 *
	 * @param int Length of password to generate
	 * return string Random password of supplied length
	 */
	function _randomPassword ($length = 7) {
		$salt = "abcdefghijklmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ123456789";  // salt to select chars from
		srand((double)microtime()*1000000); // start the random generator
		$password=""; // set the inital variable
		for ($i=0;$i<$length;$i++) {  // loop and create password
			$password = $password . substr ($salt, rand() % strlen($salt), 1);
		}
		return $password;
	}
	/**
	 *  Send templated email
	 */
	function _sendMailTemplate($to, $from, $subject, $template) {
		$this->Email->to = $to;
		$this->Email->subject = $subject;
		$this->Email->from = $from;
		$this->Email->template = $template;
		return $this->Email->send();
	}
	
	
	function _setParentAro($userid, $parent_id)
    {
        // we first retrieve the Aro of this use
        
        $aro = $this->Acl->Aro->node(array('model' => 'User', 'foreign_key' => $userid));
        
        if(empty($aro))
            return;
            
        $aronode = $aro[0]['Aro'];
        // parent did not change

        if($aronode['parent_id'] == $userid)
            return;
        // we first need to find the aro id of the new parent
        
        $arop = $this->Acl->Aro->node(array('model' => 'Role', 'foreign_key' => $parent_id));
        
        if(!empty($arop))
        {
            $newid = $arop[0]['Aro']['id'];
            $aronode['parent_id'] = $newid;
            $this->Acl->Aro->save($aronode);
        }
        else
            echo "Error resetting the parent ARO";
    }
	
	function profile()
	{
		$id = $this->Auth->user('id');
		if (!$id && empty($this->data)) {
			$this->Session->setFlash('Invalid User');
			$this->redirect(array('action'=>'index'), null, true);
		}
		if (!empty($this->data)) {
			$this->data['User']['id'] = $id;

			//  If user leaves blank, don't
			if (empty($this->data['User']['new_password']))	{
				$this->__unsetPassword();
			}
			if ($this->User->save($this->data, true, array('username', 'fname', 'lname', 'email', 'password'))) 	{
				$this->Session->setFlash(__('Your profile has been saved', true),'flash_success');
				$this->redirect('/');
			} else { // clear these fields or else they'll be repopulated with hashes. Passwords should be cleared anyway.
				$this->__unsetPassword();
				$this->Session->setFlash(__('The Profile could not be saved. Please, try again.', true),'flash_failure');
			}
		}

		if (empty($this->data)) {
			$this->data = $this->User->read(null, $id);
		}
	}
	
	 /**
     * sets the language
     *
     * todo: when the user is logged in, selected language should be saved
     *       to the database
     */
    public function switch_language($language) {
		
		
        $language = $language;
        $languages = Configure::read('Languages');
        if(!isset($languages[$language])) {
            $language = 'en-en';
        } 
        
        $this->Session->write('Config.language', $language);
        # now set the language
        $this->L10n->get($language);

        setlocale(LC_ALL, 
            substr($this->L10n->locale, 0, 3) .
            strtoupper(substr($this->L10n->locale, 3, 2)) . 
            '.' . $this->L10n->charset
        );
        
        
        $this->redirect($this->referer());
		
    }
	
}
?>
